我试图回答这个问题,因为我认为我知道答案.事实证明,我不太了解:/
这是我做过的测试:
class Inst[T] { def is(x: Any) = scala.util.Try { as(x) }.isSuccess def as(x: Any): T = x.asInstanceOf[T] } scala> new Inst[String].is(3) res17: Boolean = true scala> new Inst[String].as(3) java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String ... 33 elided
这里发生了什么?为什么只有第二次as
投掷,而不是第一次?
这是因为只有在使用值执行某些操作时才会抛出class-cast-exception,在执行后调用它上面的方法.例如,在REPL中,您将toString
在第二种情况下进行呼叫.注意:
new Inst[String].as(3); () // nothing happens new Inst[String].as(3).toString; () // exception
这需要额外步骤的原因是在运行时擦除的Inst[T]
类型参数是通用的T
; 只有当调用站点(具有静态类型知识T
)尝试在结果上调用方法时,才会进行实际的类型检查.
对于你的后续问题,toString
是在任何对象上定义的,因为它T
是通用的,你有一个盒装整数(<: AnyRef
),toString
并且println
在is
方法中成功.所以Try
失败的另一个例子是:
class Inst[T] { def foo(x: Any)(implicit ev: T <:< String) = scala.util.Try { ev(as(x)).reverse }.isSuccess } new Inst[String].foo(3) // false!